package leetcode.editor.cn;//给定一个整数数组 nums 和一个正整数 k，找出是否有可能把这个数组分成 k 个非空子集，其总和都相等。
//
//
//
// 示例 1：
//
//
//输入： nums = [4, 3, 2, 3, 5, 2, 1], k = 4
//输出： True
//说明： 有可能将其分成 4 个子集（5），（1,4），（2,3），（2,3）等于总和。
//
// 示例 2:
//
//
//输入: nums = [1,2,3,4], k = 3
//输出: false
//
//
//
// 提示：
//
//
// 1 <= k <= len(nums) <= 16
// 0 < nums[i] < 10000
// 每个元素的频率在 [1,4] 范围内
//
// Related Topics 位运算 记忆化搜索 数组 动态规划 回溯 状态压缩
// 👍 507 👎 0

/**
题目：划分为k个相等的子集
2022-03-07 22:12:17
*/
public class PartitionToKEqualSumSubsets698{
    public static void main(String[] args) {
        Solution solution = new PartitionToKEqualSumSubsets698().new Solution();
        // TO TEST
    }

    //leetcode submit region begin(Prohibit modification and deletion)
    class Solution {
        public boolean canPartitionKSubsets(int[] nums, int k) {
            if(k>nums.length) return false;
            int sum=0;
            for (int num:nums) sum += num;
            if (sum%k != 0) return false;
            int[] bucket = new int[k];
            int target = sum/k;
            return backtrack(nums, 0, bucket, target);
        }

        boolean backtrack(int[] nums, int index, int[] bucket, int target){
            if (index==nums.length){
                for (int b:bucket){
                    if (b!=target) return false;
                }
                return true;
            }
            for (int i = 0; i < bucket.length; i++) {
                if (bucket[i]+nums[index]>target){
                    continue;
                }
                bucket[i] += nums[index];
                if (backtrack(nums, index+1, bucket, target)){
                    return true;
                }
                bucket[i] -= nums[index];
            }
            return false;
        }
    }
//leetcode submit region end(Prohibit modification and deletion)

}
